/* who3.c - 使用缓冲读取的 who 程序  
 *          - 抑制空记录  
 *          - 格式化时间  
 *          - 缓冲输入（使用 utmplib）  
 */  
#include <stdio.h>  
#include <stdlib.h>    /* 添加 stdlib.h 以使用 exit() */  
#include <sys/types.h>  
#include <utmp.h>  
#include <fcntl.h>  
#include <time.h>  

/* 定义宏以在输出中包含远程主机信息 */  
#define SHOWHOST  

/* 函数声明 */  
void show_info(struct utmp *);  
void showtime(time_t);  

/* utmplib 库函数的声明（假设 utmplib 提供这些函数） */  
int utmp_open(char *);  
struct utmp *utmp_next(void);  
void utmp_close(void);  

int main()  
{  
    struct utmp *utbufp;       /* 指向下一个记录的指针 */  
    
    /* 以只读方式打开 UTMP 文件 */  
    if (utmp_open(UTMP_FILE) == -1) {  
        perror(UTMP_FILE);    /* UTMP_FILE 定义在 utmp.h */  
        return 1;             /* 返回错误码 */  
    }  

    /* 读取 UTMP 文件中的记录并显示信息 */  
    while ((utbufp = utmp_next()) != NULL) {  
        show_info(utbufp);  
    }  

    /* 关闭 UTMP 文件 */  
    utmp_close();  
    return 0;                   /* 正常退出 */  
}  

/*  
 * show_info()  
 *      以人类可读的形式显示 utmp 结构体的内容  
 *      如果记录没有用户名，则不显示任何内容  
 */  
void show_info(struct utmp *utbufp)  
{  
    /* 仅处理用户进程类型的记录 */  
    if (utbufp->ut_type != USER_PROCESS) {  
        return;  
    }  

    printf("%-8.8s", utbufp->ut_name);    /* 登录名 */  
    printf(" ");                           /* 一个空格 */  
    printf("%-8.8s", utbufp->ut_line);    /* 终端 */  
    printf(" ");                           /* 一个空格 */  
    showtime(utbufp->ut_time);            /* 显示登录时间 */  
#ifdef SHOWHOST  
    if (utbufp->ut_host[0] != '\0') {  
        printf(" (%s)", utbufp->ut_host); /* 主机名 */  
    }  
#endif  
    printf("\n");                          /* 换行 */  
}  

/*  
 * showtime()  
 *      以适合人类阅读的格式显示时间  
 *      使用 ctime 将时间转换为字符串，然后提取其中的部分  
 *      注意：%12.12s 打印 12 个字符宽度的字符串，并限制为 12 个字符  
 */  
void showtime(time_t timeval)  
{  
    char *cp; /* 用于存储时间字符串的指针 */  

    cp = ctime(&timeval);           /* 将时间转换为字符串 */  
                                    /* 字符串格式如下：  
                                     * Mon Feb  4 00:46:40 EST 1991  
                                     * 0123456789012345...  
                                     */  
    printf("%12.12s", cp + 4);      /* 从位置 4 开始选择 12 个字符 */  
}
